////***************************************************************************************
//// WavesCSApp.cpp by Frank Luna (C) 2015 All Rights Reserved.
////***************************************************************************************
//
//#include "../../../Common/d3dApp.h"
//#include "../../../Common/MathHelper.h"
//#include "../../../Common/UploadBuffer.h"
//#include "../../../Common/GeometryGenerator.h"
//#include "WavesCSFrameResource.h"
//#include "GpuWavesCS.h"
//
//using Microsoft::WRL::ComPtr;
//using namespace DirectX;
//using namespace DirectX::PackedVector;
//
//#pragma comment(lib, "d3dcompiler.lib")
//#pragma comment(lib, "D3D12.lib")
//
//const int gNumFrameResources = 3;
//
//// Lightweight structure stores parameters to draw a shape.  This will
//// vary from app-to-app.
//struct RenderItem
//{
//	RenderItem() = default;
//
//    // World matrix of the shape that describes the object's local space
//    // relative to the world space, which defines the position, orientation,
//    // and scale of the object in the world.
//    XMFLOAT4X4 World = MathHelper::Identity4x4();
//
//	XMFLOAT4X4 TexTransform = MathHelper::Identity4x4();
//
//	// Used for GPU waves render items.
//	DirectX::XMFLOAT2 DisplacementMapTexelSize = { 1.0f, 1.0f };
//	float GridSpatialStep = 1.0f;
//
//	// Dirty flag indicating the object data has changed and we need to update the constant buffer.
//	// Because we have an object cbuffer for each FrameResource, we have to apply the
//	// update to each FrameResource.  Thus, when we modify obect data we should set 
//	// NumFramesDirty = gNumFrameResources so that each frame resource gets the update.
//	int NumFramesDirty = gNumFrameResources;
//
//	// Index into GPU constant buffer corresponding to the ObjectCB for this render item.
//	UINT ObjCBIndex = -1;
//
//	Material* Mat = nullptr;
//	MeshGeometry* Geo = nullptr;
//
//    // Primitive topology.
//    D3D12_PRIMITIVE_TOPOLOGY PrimitiveType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
//
//    // DrawIndexedInstanced parameters.
//    UINT IndexCount = 0;
//    UINT StartIndexLocation = 0;
//    int BaseVertexLocation = 0;
//};
//
//enum class RenderLayer : int
//{
//	Opaque = 0,
//	Transparent,
//	AlphaTested,
//    GpuWavesCS,
//	Count
//};
//
//class WavesCSApp : public D3DApp
//{
//public:
//    WavesCSApp(HINSTANCE hInstance);
//    WavesCSApp(const WavesCSApp& rhs) = delete;
//    WavesCSApp& operator=(const WavesCSApp& rhs) = delete;
//    ~WavesCSApp();
//
//    virtual bool Initialize()override;
//
//private:
//    virtual void OnResize()override;
//    virtual void Update(const GameTimer& gt)override;
//    virtual void Draw(const GameTimer& gt)override;
//
//    virtual void OnMouseDown(WPARAM btnState, int x, int y)override;
//    virtual void OnMouseUp(WPARAM btnState, int x, int y)override;
//    virtual void OnMouseMove(WPARAM btnState, int x, int y)override;
//
//    void OnKeyboardInput(const GameTimer& gt);
//	void UpdateCamera(const GameTimer& gt);
//	void AnimateMaterials(const GameTimer& gt);
//	void UpdateObjectCBs(const GameTimer& gt);
//	void UpdateMaterialCBs(const GameTimer& gt);
//	void UpdateMainPassCB(const GameTimer& gt);
//	void UpdateWavesGPU(const GameTimer& gt);
//
//	void LoadTextures();
//    void BuildRootSignature();
//	void BuildWavesRootSignature();
//	void BuildDescriptorHeaps();
//    void BuildShadersAndInputLayout();
//    void BuildLandGeometry();
//    void BuildWavesGeometry();
//	void BuildBoxGeometry();
//    void BuildPSOs();
//    void BuildFrameResources();
//    void BuildMaterials();
//    void BuildRenderItems();
//    void DrawRenderItems(ID3D12GraphicsCommandList* cmdList, const std::vector<RenderItem*>& ritems);
//
//	std::array<const CD3DX12_STATIC_SAMPLER_DESC, 6> GetStaticSamplers();
//
//    float GetHillsHeight(float x, float z)const;
//    XMFLOAT3 GetHillsNormal(float x, float z)const;
//
//private:
//
//    std::vector<std::unique_ptr<WavesCSFrameResource>> mFrameResources;
//    WavesCSFrameResource* mCurrFrameResource = nullptr;
//    int mCurrFrameResourceIndex = 0;
//
//    UINT mCbvSrvDescriptorSize = 0;
//
//    ComPtr<ID3D12RootSignature> mRootSignature = nullptr;
//	ComPtr<ID3D12RootSignature> mWavesRootSignature = nullptr;
//
//	ComPtr<ID3D12DescriptorHeap> mSrvDescriptorHeap = nullptr;
//
//	std::unordered_map<std::string, std::unique_ptr<MeshGeometry>> mGeometries;
//	std::unordered_map<std::string, std::unique_ptr<Material>> mMaterials;
//	std::unordered_map<std::string, std::unique_ptr<Texture>> mTextures;
//	std::unordered_map<std::string, ComPtr<ID3DBlob>> mShaders;
//	std::unordered_map<std::string, ComPtr<ID3D12PipelineState>> mPSOs;
//
//    std::vector<D3D12_INPUT_ELEMENT_DESC> mInputLayout;
// 
//	// List of all the render items.
//	std::vector<std::unique_ptr<RenderItem>> mAllRitems;
//
//	// Render items divided by PSO.
//	std::vector<RenderItem*> mRitemLayer[(int)RenderLayer::Count];
//
//	std::unique_ptr<GpuWavesCS> mWaves;
//
//    PassConstants mMainPassCB;
//
//	XMFLOAT3 mEyePos = { 0.0f, 0.0f, 0.0f };
//	XMFLOAT4X4 mView = MathHelper::Identity4x4();
//	XMFLOAT4X4 mProj = MathHelper::Identity4x4();
//
//    float mTheta = 1.5f*XM_PI;
//    float mPhi = XM_PIDIV2 - 0.1f;
//    float mRadius = 50.0f;
//
//    POINT mLastMousePos;
//};
//
//int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE prevInstance,
//    PSTR cmdLine, int showCmd)
//{
//    // Enable run-time memory check for debug builds.
//#if defined(DEBUG) | defined(_DEBUG)
//    _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
//#endif
//
//    try
//    {
//        WavesCSApp theApp(hInstance);
//        if(!theApp.Initialize())
//            return 0;
//
//        return theApp.Run();
//    }
//    catch(DxException& e)
//    {
//        MessageBox(nullptr, e.ToString().c_str(), L"HR Failed", MB_OK);
//        return 0;
//    }
//}
//
//WavesCSApp::WavesCSApp(HINSTANCE hInstance)
//    : D3DApp(hInstance)
//{
//}
//
//WavesCSApp::~WavesCSApp()
//{
//    if(md3dDevice != nullptr)
//        FlushCommandQueue();
//}
//
//bool WavesCSApp::Initialize()
//{
//    if(!D3DApp::Initialize())
//        return false;
//
//    // Reset the command list to prep for initialization commands.
//    ThrowIfFailed(mCommandList->Reset(mDirectCmdListAlloc.Get(), nullptr));
//
//    // Get the increment size of a descriptor in this heap type.  This is hardware specific, 
//	// so we have to query this information.
//    mCbvSrvDescriptorSize = md3dDevice->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
//
//    mWaves = std::make_unique<GpuWavesCS>(
//		md3dDevice.Get(), 
//		mCommandList.Get(),
//		256, 256, 0.25f, 0.03f, 2.0f, 0.2f);
// 
//	LoadTextures();
//    BuildRootSignature();
//	BuildWavesRootSignature();
//	BuildDescriptorHeaps();
//    BuildShadersAndInputLayout();
//    BuildLandGeometry();
//    BuildWavesGeometry();
//	BuildBoxGeometry();
//	BuildMaterials();
//    BuildRenderItems();
//    BuildFrameResources();
//    BuildPSOs();
//
//    // Execute the initialization commands.
//    ThrowIfFailed(mCommandList->Close());
//    ID3D12CommandList* cmdsLists[] = { mCommandList.Get() };
//    mCommandQueue->ExecuteCommandLists(_countof(cmdsLists), cmdsLists);
//
//    // Wait until initialization is complete.
//    FlushCommandQueue();
//
//    return true;
//}
// 
//void WavesCSApp::OnResize()
//{
//    D3DApp::OnResize();
//
//    // The window resized, so update the aspect ratio and recompute the projection matrix.
//    XMMATRIX P = XMMatrixPerspectiveFovLH(0.25f*MathHelper::Pi, AspectRatio(), 1.0f, 1000.0f);
//    XMStoreFloat4x4(&mProj, P);
//}
//
//void WavesCSApp::Update(const GameTimer& gt)
//{
//    OnKeyboardInput(gt);
//	UpdateCamera(gt);
//
//    // Cycle through the circular frame resource array.
//    mCurrFrameResourceIndex = (mCurrFrameResourceIndex + 1) % gNumFrameResources;
//    mCurrFrameResource = mFrameResources[mCurrFrameResourceIndex].get();
//
//    // Has the GPU finished processing the commands of the current frame resource?
//    // If not, wait until the GPU has completed commands up to this fence point.
//    if(mCurrFrameResource->Fence != 0 && mFence->GetCompletedValue() < mCurrFrameResource->Fence)
//    {
//        HANDLE eventHandle = CreateEventEx(nullptr, false, false, EVENT_ALL_ACCESS);
//        ThrowIfFailed(mFence->SetEventOnCompletion(mCurrFrameResource->Fence, eventHandle));
//        WaitForSingleObject(eventHandle, INFINITE);
//        CloseHandle(eventHandle);
//    }
//
//	AnimateMaterials(gt);
//	UpdateObjectCBs(gt);
//	UpdateMaterialCBs(gt);
//	UpdateMainPassCB(gt);
//}
//
//void WavesCSApp::Draw(const GameTimer& gt)
//{
//    auto cmdListAlloc = mCurrFrameResource->CmdListAlloc;
//
//    // Reuse the memory associated with command recording.
//    // We can only reset when the associated command lists have finished execution on the GPU.
//    ThrowIfFailed(cmdListAlloc->Reset());
//
//    // A command list can be reset after it has been added to the command queue via ExecuteCommandList.
//    // Reusing the command list reuses memory.
//    ThrowIfFailed(mCommandList->Reset(cmdListAlloc.Get(), mPSOs["opaque"].Get()));
//
//	ID3D12DescriptorHeap* descriptorHeaps[] = { mSrvDescriptorHeap.Get() };
//	mCommandList->SetDescriptorHeaps(_countof(descriptorHeaps), descriptorHeaps);
//
//	UpdateWavesGPU(gt);
//
//	mCommandList->SetPipelineState(mPSOs["opaque"].Get());
//
//    mCommandList->RSSetViewports(1, &mScreenViewport);
//    mCommandList->RSSetScissorRects(1, &mScissorRect);
//
//    // Indicate a state transition on the resource usage.
//	mCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(CurrentBackBuffer(),
//		D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RENDER_TARGET));
//
//    // Clear the back buffer and depth buffer.
//    mCommandList->ClearRenderTargetView(CurrentBackBufferView(), (float*)&mMainPassCB.FogColor, 0, nullptr);
//    mCommandList->ClearDepthStencilView(DepthStencilView(), D3D12_CLEAR_FLAG_DEPTH | D3D12_CLEAR_FLAG_STENCIL, 1.0f, 0, 0, nullptr);
//
//    // Specify the buffers we are going to render to.
//    mCommandList->OMSetRenderTargets(1, &CurrentBackBufferView(), true, &DepthStencilView());
//
//	mCommandList->SetGraphicsRootSignature(mRootSignature.Get());
//
//	auto passCB = mCurrFrameResource->PassCB->Resource();
//	mCommandList->SetGraphicsRootConstantBufferView(2, passCB->GetGPUVirtualAddress());
//
//	mCommandList->SetGraphicsRootDescriptorTable(4, mWaves->DisplacementMap());
//
//    DrawRenderItems(mCommandList.Get(), mRitemLayer[(int)RenderLayer::Opaque]);
//
//	mCommandList->SetPipelineState(mPSOs["alphaTested"].Get());
//	DrawRenderItems(mCommandList.Get(), mRitemLayer[(int)RenderLayer::AlphaTested]);
//
//	mCommandList->SetPipelineState(mPSOs["transparent"].Get());
//	DrawRenderItems(mCommandList.Get(), mRitemLayer[(int)RenderLayer::Transparent]);
//
//	mCommandList->SetPipelineState(mPSOs["wavesRender"].Get());
//	DrawRenderItems(mCommandList.Get(), mRitemLayer[(int)RenderLayer::GpuWavesCS]);
//
//    // Indicate a state transition on the resource usage.
//	mCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(CurrentBackBuffer(),
//		D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT));
//
//    // Done recording commands.
//    ThrowIfFailed(mCommandList->Close());
//
//    // Add the command list to the queue for execution.
//    ID3D12CommandList* cmdsLists[] = { mCommandList.Get() };
//    mCommandQueue->ExecuteCommandLists(_countof(cmdsLists), cmdsLists);
//
//    // Swap the back and front buffers
//    ThrowIfFailed(mSwapChain->Present(0, 0));
//	mCurrBackBuffer = (mCurrBackBuffer + 1) % SwapChainBufferCount;
//
//    // Advance the fence value to mark commands up to this fence point.
//    mCurrFrameResource->Fence = ++mCurrentFence;
//
//    // Add an instruction to the command queue to set a new fence point. 
//    // Because we are on the GPU timeline, the new fence point won't be 
//    // set until the GPU finishes processing all the commands prior to this Signal().
//    mCommandQueue->Signal(mFence.Get(), mCurrentFence);
//}
//
//void WavesCSApp::OnMouseDown(WPARAM btnState, int x, int y)
//{
//    mLastMousePos.x = x;
//    mLastMousePos.y = y;
//
//    SetCapture(mhMainWnd);
//}
//
//void WavesCSApp::OnMouseUp(WPARAM btnState, int x, int y)
//{
//    ReleaseCapture();
//}
//
//void WavesCSApp::OnMouseMove(WPARAM btnState, int x, int y)
//{
//    if((btnState & MK_LBUTTON) != 0)
//    {
//        // Make each pixel correspond to a quarter of a degree.
//        float dx = XMConvertToRadians(0.25f*static_cast<float>(x - mLastMousePos.x));
//        float dy = XMConvertToRadians(0.25f*static_cast<float>(y - mLastMousePos.y));
//
//        // Update angles based on input to orbit camera around box.
//        mTheta += dx;
//        mPhi += dy;
//
//        // Restrict the angle mPhi.
//        mPhi = MathHelper::Clamp(mPhi, 0.1f, MathHelper::Pi - 0.1f);
//    }
//    else if((btnState & MK_RBUTTON) != 0)
//    {
//        // Make each pixel correspond to 0.2 unit in the scene.
//        float dx = 0.2f*static_cast<float>(x - mLastMousePos.x);
//        float dy = 0.2f*static_cast<float>(y - mLastMousePos.y);
//
//        // Update the camera radius based on input.
//        mRadius += dx - dy;
//
//        // Restrict the radius.
//        mRadius = MathHelper::Clamp(mRadius, 5.0f, 150.0f);
//    }
//
//    mLastMousePos.x = x;
//    mLastMousePos.y = y;
//}
// 
//void WavesCSApp::OnKeyboardInput(const GameTimer& gt)
//{
//}
// 
//void WavesCSApp::UpdateCamera(const GameTimer& gt)
//{
//	// Convert Spherical to Cartesian coordinates.
//	mEyePos.x = mRadius*sinf(mPhi)*cosf(mTheta);
//	mEyePos.z = mRadius*sinf(mPhi)*sinf(mTheta);
//	mEyePos.y = mRadius*cosf(mPhi);
//
//	// Build the view matrix.
//	XMVECTOR pos = XMVectorSet(mEyePos.x, mEyePos.y, mEyePos.z, 1.0f);
//	XMVECTOR target = XMVectorZero();
//	XMVECTOR up = XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f);
//
//	XMMATRIX view = XMMatrixLookAtLH(pos, target, up);
//	XMStoreFloat4x4(&mView, view);
//}
//
//void WavesCSApp::AnimateMaterials(const GameTimer& gt)
//{
//	// Scroll the water material texture coordinates.
//	auto waterMat = mMaterials["water"].get();
//
//	float& tu = waterMat->MatTransform(3, 0);
//	float& tv = waterMat->MatTransform(3, 1);
//
//	tu += 0.1f * gt.DeltaTime();
//	tv += 0.02f * gt.DeltaTime();
//
//	if(tu >= 1.0f)
//		tu -= 1.0f;
//
//	if(tv >= 1.0f)
//		tv -= 1.0f;
//
//	waterMat->MatTransform(3, 0) = tu;
//	waterMat->MatTransform(3, 1) = tv;
//
//	// Material has changed, so need to update cbuffer.
//	waterMat->NumFramesDirty = gNumFrameResources;
//}
//
//void WavesCSApp::UpdateObjectCBs(const GameTimer& gt)
//{
//	auto currObjectCB = mCurrFrameResource->ObjectCB.get();
//	for(auto& e : mAllRitems)
//	{
//		// Only update the cbuffer data if the constants have changed.  
//		// This needs to be tracked per frame resource.
//		if(e->NumFramesDirty > 0)
//		{
//			XMMATRIX world = XMLoadFloat4x4(&e->World);
//			XMMATRIX texTransform = XMLoadFloat4x4(&e->TexTransform);
//
//			ObjectConstants objConstants;
//			XMStoreFloat4x4(&objConstants.World, XMMatrixTranspose(world));
//			XMStoreFloat4x4(&objConstants.TexTransform, XMMatrixTranspose(texTransform));
//			objConstants.DisplacementMapTexelSize = e->DisplacementMapTexelSize;
//			objConstants.GridSpatialStep = e->GridSpatialStep;
//
//			currObjectCB->CopyData(e->ObjCBIndex, objConstants);
//
//			// Next FrameResource need to be updated too.
//			e->NumFramesDirty--;
//		}
//	}
//}
//
//void WavesCSApp::UpdateMaterialCBs(const GameTimer& gt)
//{
//	auto currMaterialCB = mCurrFrameResource->MaterialCB.get();
//	for(auto& e : mMaterials)
//	{
//		// Only update the cbuffer data if the constants have changed.  If the cbuffer
//		// data changes, it needs to be updated for each FrameResource.
//		Material* mat = e.second.get();
//		if(mat->NumFramesDirty > 0)
//		{
//			XMMATRIX matTransform = XMLoadFloat4x4(&mat->MatTransform);
//
//			MaterialConstants matConstants;
//			matConstants.DiffuseAlbedo = mat->DiffuseAlbedo;
//			matConstants.FresnelR0 = mat->FresnelR0;
//			matConstants.Roughness = mat->Roughness;
//			XMStoreFloat4x4(&matConstants.MatTransform, XMMatrixTranspose(matTransform));
//
//			currMaterialCB->CopyData(mat->MatCBIndex, matConstants);
//
//			// Next FrameResource need to be updated too.
//			mat->NumFramesDirty--;
//		}
//	}
//}
//
//void WavesCSApp::UpdateMainPassCB(const GameTimer& gt)
//{
//	XMMATRIX view = XMLoadFloat4x4(&mView);
//	XMMATRIX proj = XMLoadFloat4x4(&mProj);
//
//	XMMATRIX viewProj = XMMatrixMultiply(view, proj);
//	XMMATRIX invView = XMMatrixInverse(&XMMatrixDeterminant(view), view);
//	XMMATRIX invProj = XMMatrixInverse(&XMMatrixDeterminant(proj), proj);
//	XMMATRIX invViewProj = XMMatrixInverse(&XMMatrixDeterminant(viewProj), viewProj);
//
//	XMStoreFloat4x4(&mMainPassCB.View, XMMatrixTranspose(view));
//	XMStoreFloat4x4(&mMainPassCB.InvView, XMMatrixTranspose(invView));
//	XMStoreFloat4x4(&mMainPassCB.Proj, XMMatrixTranspose(proj));
//	XMStoreFloat4x4(&mMainPassCB.InvProj, XMMatrixTranspose(invProj));
//	XMStoreFloat4x4(&mMainPassCB.ViewProj, XMMatrixTranspose(viewProj));
//	XMStoreFloat4x4(&mMainPassCB.InvViewProj, XMMatrixTranspose(invViewProj));
//	mMainPassCB.EyePosW = mEyePos;
//	mMainPassCB.RenderTargetSize = XMFLOAT2((float)mClientWidth, (float)mClientHeight);
//	mMainPassCB.InvRenderTargetSize = XMFLOAT2(1.0f / mClientWidth, 1.0f / mClientHeight);
//	mMainPassCB.NearZ = 1.0f;
//	mMainPassCB.FarZ = 1000.0f;
//	mMainPassCB.TotalTime = gt.TotalTime();
//	mMainPassCB.DeltaTime = gt.DeltaTime();
//	mMainPassCB.AmbientLight = { 0.25f, 0.25f, 0.35f, 1.0f };
//	mMainPassCB.Lights[0].Direction = { 0.57735f, -0.57735f, 0.57735f };
//	mMainPassCB.Lights[0].Strength = { 0.6f, 0.6f, 0.6f };
//	mMainPassCB.Lights[1].Direction = { -0.57735f, -0.57735f, 0.57735f };
//	mMainPassCB.Lights[1].Strength = { 0.3f, 0.3f, 0.3f };
//	mMainPassCB.Lights[2].Direction = { 0.0f, -0.707f, -0.707f };
//	mMainPassCB.Lights[2].Strength = { 0.15f, 0.15f, 0.15f };
//
//	auto currPassCB = mCurrFrameResource->PassCB.get();
//	currPassCB->CopyData(0, mMainPassCB);
//}
//
//void WavesCSApp::UpdateWavesGPU(const GameTimer& gt)
//{
//	// Every quarter second, generate a random wave.
//	static float t_base = 0.0f;
//	if((mTimer.TotalTime() - t_base) >= 0.25f)
//	{
//		t_base += 0.25f;
//
//		int i = MathHelper::Rand(4, mWaves->RowCount() - 5);
//		int j = MathHelper::Rand(4, mWaves->ColumnCount() - 5);
//
//		float r = MathHelper::RandF(1.0f, 2.0f);
//
//		mWaves->Disturb(mCommandList.Get(), mWavesRootSignature.Get(), mPSOs["wavesDisturb"].Get(), i, j, r);
//	}
//
//	// Update the wave simulation.
//	mWaves->Update(gt, mCommandList.Get(), mWavesRootSignature.Get(), mPSOs["wavesUpdate"].Get());
//}
//
//void WavesCSApp::LoadTextures()
//{
//	auto grassTex = std::make_unique<Texture>();
//	grassTex->Name = "grassTex";
//	grassTex->Filename = L"E:/DX12Book/DX12LearnProject/DX12Learn/Textures/grass.dds";
//	ThrowIfFailed(DirectX::CreateDDSTextureFromFile12(md3dDevice.Get(),
//		mCommandList.Get(), grassTex->Filename.c_str(),
//		grassTex->Resource, grassTex->UploadHeap));
//
//	auto waterTex = std::make_unique<Texture>();
//	waterTex->Name = "waterTex";
//	waterTex->Filename = L"E:/DX12Book/DX12LearnProject/DX12Learn/Textures/water1.dds";
//	ThrowIfFailed(DirectX::CreateDDSTextureFromFile12(md3dDevice.Get(),
//		mCommandList.Get(), waterTex->Filename.c_str(),
//		waterTex->Resource, waterTex->UploadHeap));
//
//	auto fenceTex = std::make_unique<Texture>();
//	fenceTex->Name = "fenceTex";
//	fenceTex->Filename = L"E:/DX12Book/DX12LearnProject/DX12Learn/Textures/WireFence.dds";
//	ThrowIfFailed(DirectX::CreateDDSTextureFromFile12(md3dDevice.Get(),
//		mCommandList.Get(), fenceTex->Filename.c_str(),
//		fenceTex->Resource, fenceTex->UploadHeap));
//
//	mTextures[grassTex->Name] = std::move(grassTex);
//	mTextures[waterTex->Name] = std::move(waterTex);
//	mTextures[fenceTex->Name] = std::move(fenceTex);
//}
//
//void WavesCSApp::BuildRootSignature()
//{
//	CD3DX12_DESCRIPTOR_RANGE texTable;
//	texTable.Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 1, 0);
//
//	CD3DX12_DESCRIPTOR_RANGE displacementMapTable;
//	displacementMapTable.Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 1, 1);
//
//    // Root parameter can be a table, root descriptor or root constants.
//    CD3DX12_ROOT_PARAMETER slotRootParameter[5];
//
//	// Perfomance TIP: Order from most frequent to least frequent.
//	slotRootParameter[0].InitAsDescriptorTable(1, &texTable, D3D12_SHADER_VISIBILITY_ALL);
//    slotRootParameter[1].InitAsConstantBufferView(0);
//    slotRootParameter[2].InitAsConstantBufferView(1);
//    slotRootParameter[3].InitAsConstantBufferView(2);
//	slotRootParameter[4].InitAsDescriptorTable(1, &displacementMapTable, D3D12_SHADER_VISIBILITY_ALL);
//
//	auto staticSamplers = GetStaticSamplers();
//
//    // A root signature is an array of root parameters.
//	CD3DX12_ROOT_SIGNATURE_DESC rootSigDesc(5, slotRootParameter,
//		(UINT)staticSamplers.size(), staticSamplers.data(),
//		D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT);
//
//    // create a root signature with a single slot which points to a descriptor range consisting of a single constant buffer
//    ComPtr<ID3DBlob> serializedRootSig = nullptr;
//    ComPtr<ID3DBlob> errorBlob = nullptr;
//    HRESULT hr = D3D12SerializeRootSignature(&rootSigDesc, D3D_ROOT_SIGNATURE_VERSION_1,
//        serializedRootSig.GetAddressOf(), errorBlob.GetAddressOf());
//
//    if(errorBlob != nullptr)
//    {
//        ::OutputDebugStringA((char*)errorBlob->GetBufferPointer());
//    }
//    ThrowIfFailed(hr);
//
//    ThrowIfFailed(md3dDevice->CreateRootSignature(
//		0,
//        serializedRootSig->GetBufferPointer(),
//        serializedRootSig->GetBufferSize(),
//        IID_PPV_ARGS(mRootSignature.GetAddressOf())));
//}
//
//void WavesCSApp::BuildWavesRootSignature()
//{
//	CD3DX12_DESCRIPTOR_RANGE uavTable0;
//	uavTable0.Init(D3D12_DESCRIPTOR_RANGE_TYPE_UAV, 1, 0);
//
//	CD3DX12_DESCRIPTOR_RANGE uavTable1;
//	uavTable1.Init(D3D12_DESCRIPTOR_RANGE_TYPE_UAV, 1, 1);
//
//	CD3DX12_DESCRIPTOR_RANGE uavTable2;
//	uavTable2.Init(D3D12_DESCRIPTOR_RANGE_TYPE_UAV, 1, 2);
//
//	// Root parameter can be a table, root descriptor or root constants.
//	CD3DX12_ROOT_PARAMETER slotRootParameter[4];
//
//	// Perfomance TIP: Order from most frequent to least frequent.
//	slotRootParameter[0].InitAsConstants(6, 0);
//	slotRootParameter[1].InitAsDescriptorTable(1, &uavTable0);
//	slotRootParameter[2].InitAsDescriptorTable(1, &uavTable1);
//	slotRootParameter[3].InitAsDescriptorTable(1, &uavTable2);
//
//	// A root signature is an array of root parameters.
//	CD3DX12_ROOT_SIGNATURE_DESC rootSigDesc(4, slotRootParameter,
//		0, nullptr,
//		D3D12_ROOT_SIGNATURE_FLAG_NONE);
//
//	// create a root signature with a single slot which points to a descriptor range consisting of a single constant buffer
//	ComPtr<ID3DBlob> serializedRootSig = nullptr;
//	ComPtr<ID3DBlob> errorBlob = nullptr;
//	HRESULT hr = D3D12SerializeRootSignature(&rootSigDesc, D3D_ROOT_SIGNATURE_VERSION_1,
//		serializedRootSig.GetAddressOf(), errorBlob.GetAddressOf());
//
//	if(errorBlob != nullptr)
//	{
//		::OutputDebugStringA((char*)errorBlob->GetBufferPointer());
//	}
//	ThrowIfFailed(hr);
//
//	ThrowIfFailed(md3dDevice->CreateRootSignature(
//		0,
//		serializedRootSig->GetBufferPointer(),
//		serializedRootSig->GetBufferSize(),
//		IID_PPV_ARGS(mWavesRootSignature.GetAddressOf())));
//}
//
//void WavesCSApp::BuildDescriptorHeaps()
//{
//	UINT srvCount = 3;
//
//	//
//	// Create the SRV heap.
//	//
//	D3D12_DESCRIPTOR_HEAP_DESC srvHeapDesc = {};
//	srvHeapDesc.NumDescriptors = srvCount + mWaves->DescriptorCount();
//	srvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
//	srvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
//	ThrowIfFailed(md3dDevice->CreateDescriptorHeap(&srvHeapDesc, IID_PPV_ARGS(&mSrvDescriptorHeap)));
//
//	//
//	// Fill out the heap with actual descriptors.  
//	//
//	CD3DX12_CPU_DESCRIPTOR_HANDLE hDescriptor(mSrvDescriptorHeap->GetCPUDescriptorHandleForHeapStart());
//
//	auto grassTex = mTextures["grassTex"]->Resource;
//	auto waterTex = mTextures["waterTex"]->Resource;
//	auto fenceTex = mTextures["fenceTex"]->Resource;
//
//	D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
//	srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
//	srvDesc.Format = grassTex->GetDesc().Format;
//	srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
//	srvDesc.Texture2D.MostDetailedMip = 0;
//	srvDesc.Texture2D.MipLevels = -1;
//	md3dDevice->CreateShaderResourceView(grassTex.Get(), &srvDesc, hDescriptor);
//
//	// next descriptor
//	hDescriptor.Offset(1, mCbvSrvDescriptorSize);
//
//	srvDesc.Format = waterTex->GetDesc().Format;
//	md3dDevice->CreateShaderResourceView(waterTex.Get(), &srvDesc, hDescriptor);
//
//	// next descriptor
//	hDescriptor.Offset(1, mCbvSrvDescriptorSize);
//
//	srvDesc.Format = fenceTex->GetDesc().Format;
//	md3dDevice->CreateShaderResourceView(fenceTex.Get(), &srvDesc, hDescriptor);
//
//	mWaves->BuildDescriptors(
//		CD3DX12_CPU_DESCRIPTOR_HANDLE(mSrvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), srvCount, mCbvSrvDescriptorSize),
//		CD3DX12_GPU_DESCRIPTOR_HANDLE(mSrvDescriptorHeap->GetGPUDescriptorHandleForHeapStart(), srvCount, mCbvSrvDescriptorSize),
//		mCbvSrvDescriptorSize);
//}
//
//void WavesCSApp::BuildShadersAndInputLayout()
//{
//	const D3D_SHADER_MACRO defines[] =
//	{
//		"FOG", "1",
//		NULL, NULL
//	};
//
//	const D3D_SHADER_MACRO alphaTestDefines[] =
//	{
//		"FOG", "1",
//		"ALPHA_TEST", "1",
//		NULL, NULL
//	};
//
//	const D3D_SHADER_MACRO waveDefines[] =
//	{
//		"DISPLACEMENT_MAP", "1",
//		NULL, NULL
//	};
//
//	mShaders["standardVS"] = d3dUtil::CompileShader(L"E:\\DX12Book\\DX12LearnProject\\DX12Learn\\LearnDemo\\Chapter 13 The Compute Shader\\WavesCS\\Shaders\\Default.hlsl", nullptr, "VS", "vs_5_0");
//	mShaders["wavesVS"] = d3dUtil::CompileShader(L"E:\\DX12Book\\DX12LearnProject\\DX12Learn\\LearnDemo\\Chapter 13 The Compute Shader\\WavesCS\\Shaders\\Default.hlsl", waveDefines, "VS", "vs_5_0");
//	mShaders["opaquePS"] = d3dUtil::CompileShader(L"E:\\DX12Book\\DX12LearnProject\\DX12Learn\\LearnDemo\\Chapter 13 The Compute Shader\\WavesCS\\Shaders\\Default.hlsl", defines, "PS", "ps_5_0");
//	mShaders["alphaTestedPS"] = d3dUtil::CompileShader(L"E:\\DX12Book\\DX12LearnProject\\DX12Learn\\LearnDemo\\Chapter 13 The Compute Shader\\WavesCS\\Shaders\\Default.hlsl", alphaTestDefines, "PS", "ps_5_0");
//	mShaders["wavesUpdateCS"] = d3dUtil::CompileShader(L"E:\\DX12Book\\DX12LearnProject\\DX12Learn\\LearnDemo\\Chapter 13 The Compute Shader\\WavesCS\\Shaders\\WaveSim.hlsl", nullptr, "UpdateWavesCS", "cs_5_0");
//	mShaders["wavesDisturbCS"] = d3dUtil::CompileShader(L"E:\\DX12Book\\DX12LearnProject\\DX12Learn\\LearnDemo\\Chapter 13 The Compute Shader\\WavesCS\\Shaders\\WaveSim.hlsl", nullptr, "DisturbWavesCS", "cs_5_0");
//
//    mInputLayout =
//    {
//        { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
//        { "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
//		{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 24, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
//    };
//}
//
//void WavesCSApp::BuildLandGeometry()
//{
//    GeometryGenerator geoGen;
//    GeometryGenerator::MeshData grid = geoGen.CreateGrid(160.0f, 160.0f, 50, 50);
//
//    //
//    // Extract the vertex elements we are interested and apply the height function to
//    // each vertex.  In addition, color the vertices based on their height so we have
//    // sandy looking beaches, grassy low hills, and snow mountain peaks.
//    //
//
//    std::vector<Vertex> vertices(grid.Vertices.size());
//    for(size_t i = 0; i < grid.Vertices.size(); ++i)
//    {
//        auto& p = grid.Vertices[i].Position;
//        vertices[i].Pos = p;
//        vertices[i].Pos.y = GetHillsHeight(p.x, p.z);
//        vertices[i].Normal = GetHillsNormal(p.x, p.z);
//		vertices[i].TexC = grid.Vertices[i].TexC;
//    }
//
//    const UINT vbByteSize = (UINT)vertices.size() * sizeof(Vertex);
//
//    std::vector<std::uint16_t> indices = grid.GetIndices16();
//    const UINT ibByteSize = (UINT)indices.size() * sizeof(std::uint16_t);
//
//	auto geo = std::make_unique<MeshGeometry>();
//	geo->Name = "landGeo";
//
//	ThrowIfFailed(D3DCreateBlob(vbByteSize, &geo->VertexBufferCPU));
//	CopyMemory(geo->VertexBufferCPU->GetBufferPointer(), vertices.data(), vbByteSize);
//
//	ThrowIfFailed(D3DCreateBlob(ibByteSize, &geo->IndexBufferCPU));
//	CopyMemory(geo->IndexBufferCPU->GetBufferPointer(), indices.data(), ibByteSize);
//
//	geo->VertexBufferGPU = d3dUtil::CreateDefaultBuffer(md3dDevice.Get(),
//		mCommandList.Get(), vertices.data(), vbByteSize, geo->VertexBufferUploader);
//
//	geo->IndexBufferGPU = d3dUtil::CreateDefaultBuffer(md3dDevice.Get(),
//		mCommandList.Get(), indices.data(), ibByteSize, geo->IndexBufferUploader);
//
//	geo->VertexByteStride = sizeof(Vertex);
//	geo->VertexBufferByteSize = vbByteSize;
//	geo->IndexFormat = DXGI_FORMAT_R16_UINT;
//	geo->IndexBufferByteSize = ibByteSize;
//
//	SubmeshGeometry submesh;
//	submesh.IndexCount = (UINT)indices.size();
//	submesh.StartIndexLocation = 0;
//	submesh.BaseVertexLocation = 0;
//
//	geo->DrawArgs["grid"] = submesh;
//
//	mGeometries["landGeo"] = std::move(geo);
//}
//
//void WavesCSApp::BuildWavesGeometry()
//{
//	GeometryGenerator geoGen;
//	GeometryGenerator::MeshData grid = geoGen.CreateGrid(160.0f, 160.0f, mWaves->RowCount(), mWaves->ColumnCount());
//
//	std::vector<Vertex> vertices(grid.Vertices.size());
//	for(size_t i = 0; i < grid.Vertices.size(); ++i)
//	{
//		vertices[i].Pos = grid.Vertices[i].Position;
//		vertices[i].Normal = grid.Vertices[i].Normal;
//		vertices[i].TexC = grid.Vertices[i].TexC;
//	}
//
//	std::vector<std::uint32_t> indices = grid.Indices32;
//
//	UINT vbByteSize = mWaves->VertexCount()*sizeof(Vertex);
//	UINT ibByteSize = (UINT)indices.size()*sizeof(std::uint32_t);
//
//	auto geo = std::make_unique<MeshGeometry>();
//	geo->Name = "waterGeo";
//
//	ThrowIfFailed(D3DCreateBlob(vbByteSize, &geo->VertexBufferCPU));
//	CopyMemory(geo->VertexBufferCPU->GetBufferPointer(), vertices.data(), vbByteSize);
//
//	ThrowIfFailed(D3DCreateBlob(ibByteSize, &geo->IndexBufferCPU));
//	CopyMemory(geo->IndexBufferCPU->GetBufferPointer(), indices.data(), ibByteSize);
//
//	geo->VertexBufferGPU = d3dUtil::CreateDefaultBuffer(md3dDevice.Get(),
//		mCommandList.Get(), vertices.data(), vbByteSize, geo->VertexBufferUploader);
//
//	geo->IndexBufferGPU = d3dUtil::CreateDefaultBuffer(md3dDevice.Get(),
//		mCommandList.Get(), indices.data(), ibByteSize, geo->IndexBufferUploader);
//
//	geo->VertexByteStride = sizeof(Vertex);
//	geo->VertexBufferByteSize = vbByteSize;
//	geo->IndexFormat = DXGI_FORMAT_R32_UINT;
//	geo->IndexBufferByteSize = ibByteSize;
//
//	SubmeshGeometry submesh;
//	submesh.IndexCount = (UINT)indices.size();
//	submesh.StartIndexLocation = 0;
//	submesh.BaseVertexLocation = 0;
//
//	geo->DrawArgs["grid"] = submesh;
//
//	mGeometries["waterGeo"] = std::move(geo);
//}
//
//void WavesCSApp::BuildBoxGeometry()
//{
//	GeometryGenerator geoGen;
//	GeometryGenerator::MeshData box = geoGen.CreateBox(8.0f, 8.0f, 8.0f, 3);
//
//	std::vector<Vertex> vertices(box.Vertices.size());
//	for (size_t i = 0; i < box.Vertices.size(); ++i)
//	{
//		auto& p = box.Vertices[i].Position;
//		vertices[i].Pos = p;
//		vertices[i].Normal = box.Vertices[i].Normal;
//		vertices[i].TexC = box.Vertices[i].TexC;
//	}
//
//	const UINT vbByteSize = (UINT)vertices.size() * sizeof(Vertex);
//
//	std::vector<std::uint16_t> indices = box.GetIndices16();
//	const UINT ibByteSize = (UINT)indices.size() * sizeof(std::uint16_t);
//
//	auto geo = std::make_unique<MeshGeometry>();
//	geo->Name = "boxGeo";
//
//	ThrowIfFailed(D3DCreateBlob(vbByteSize, &geo->VertexBufferCPU));
//	CopyMemory(geo->VertexBufferCPU->GetBufferPointer(), vertices.data(), vbByteSize);
//
//	ThrowIfFailed(D3DCreateBlob(ibByteSize, &geo->IndexBufferCPU));
//	CopyMemory(geo->IndexBufferCPU->GetBufferPointer(), indices.data(), ibByteSize);
//
//	geo->VertexBufferGPU = d3dUtil::CreateDefaultBuffer(md3dDevice.Get(),
//		mCommandList.Get(), vertices.data(), vbByteSize, geo->VertexBufferUploader);
//
//	geo->IndexBufferGPU = d3dUtil::CreateDefaultBuffer(md3dDevice.Get(),
//		mCommandList.Get(), indices.data(), ibByteSize, geo->IndexBufferUploader);
//
//	geo->VertexByteStride = sizeof(Vertex);
//	geo->VertexBufferByteSize = vbByteSize;
//	geo->IndexFormat = DXGI_FORMAT_R16_UINT;
//	geo->IndexBufferByteSize = ibByteSize;
//
//	SubmeshGeometry submesh;
//	submesh.IndexCount = (UINT)indices.size();
//	submesh.StartIndexLocation = 0;
//	submesh.BaseVertexLocation = 0;
//
//	geo->DrawArgs["box"] = submesh;
//
//	mGeometries["boxGeo"] = std::move(geo);
//}
//
//void WavesCSApp::BuildPSOs()
//{
//    D3D12_GRAPHICS_PIPELINE_STATE_DESC opaquePsoDesc;
//
//	//
//	// PSO for opaque objects.
//	//
//    ZeroMemory(&opaquePsoDesc, sizeof(D3D12_GRAPHICS_PIPELINE_STATE_DESC));
//	opaquePsoDesc.InputLayout = { mInputLayout.data(), (UINT)mInputLayout.size() };
//	opaquePsoDesc.pRootSignature = mRootSignature.Get();
//	opaquePsoDesc.VS = 
//	{ 
//		reinterpret_cast<BYTE*>(mShaders["standardVS"]->GetBufferPointer()), 
//		mShaders["standardVS"]->GetBufferSize()
//	};
//	opaquePsoDesc.PS = 
//	{ 
//		reinterpret_cast<BYTE*>(mShaders["opaquePS"]->GetBufferPointer()),
//		mShaders["opaquePS"]->GetBufferSize()
//	};
//	opaquePsoDesc.RasterizerState = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT);
//	opaquePsoDesc.BlendState = CD3DX12_BLEND_DESC(D3D12_DEFAULT);
//	opaquePsoDesc.DepthStencilState = CD3DX12_DEPTH_STENCIL_DESC(D3D12_DEFAULT);
//	opaquePsoDesc.SampleMask = UINT_MAX;
//	opaquePsoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
//	opaquePsoDesc.NumRenderTargets = 1;
//	opaquePsoDesc.RTVFormats[0] = mBackBufferFormat;
//	opaquePsoDesc.SampleDesc.Count = m4xMsaaState ? 4 : 1;
//	opaquePsoDesc.SampleDesc.Quality = m4xMsaaState ? (m4xMsaaQuality - 1) : 0;
//	opaquePsoDesc.DSVFormat = mDepthStencilFormat;
//    ThrowIfFailed(md3dDevice->CreateGraphicsPipelineState(&opaquePsoDesc, IID_PPV_ARGS(&mPSOs["opaque"])));
//
//	//
//	// PSO for transparent objects
//	//
//
//	D3D12_GRAPHICS_PIPELINE_STATE_DESC transparentPsoDesc = opaquePsoDesc;
//
//	D3D12_RENDER_TARGET_BLEND_DESC transparencyBlendDesc;
//	transparencyBlendDesc.BlendEnable = true;
//	transparencyBlendDesc.LogicOpEnable = false;
//	transparencyBlendDesc.SrcBlend = D3D12_BLEND_SRC_ALPHA;
//	transparencyBlendDesc.DestBlend = D3D12_BLEND_INV_SRC_ALPHA;
//	transparencyBlendDesc.BlendOp = D3D12_BLEND_OP_ADD;
//	transparencyBlendDesc.SrcBlendAlpha = D3D12_BLEND_ONE;
//	transparencyBlendDesc.DestBlendAlpha = D3D12_BLEND_ZERO;
//	transparencyBlendDesc.BlendOpAlpha = D3D12_BLEND_OP_ADD;
//	transparencyBlendDesc.LogicOp = D3D12_LOGIC_OP_NOOP;
//	transparencyBlendDesc.RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL;
//
//	transparentPsoDesc.BlendState.RenderTarget[0] = transparencyBlendDesc;
//	ThrowIfFailed(md3dDevice->CreateGraphicsPipelineState(&transparentPsoDesc, IID_PPV_ARGS(&mPSOs["transparent"])));
//
//	//
//	// PSO for alpha tested objects
//	//
//
//	D3D12_GRAPHICS_PIPELINE_STATE_DESC alphaTestedPsoDesc = opaquePsoDesc;
//	alphaTestedPsoDesc.PS = 
//	{ 
//		reinterpret_cast<BYTE*>(mShaders["alphaTestedPS"]->GetBufferPointer()),
//		mShaders["alphaTestedPS"]->GetBufferSize()
//	};
//	alphaTestedPsoDesc.RasterizerState.CullMode = D3D12_CULL_MODE_NONE;
//	ThrowIfFailed(md3dDevice->CreateGraphicsPipelineState(&alphaTestedPsoDesc, IID_PPV_ARGS(&mPSOs["alphaTested"])));
//
//	//
//	// PSO for drawing waves
//	//
//	D3D12_GRAPHICS_PIPELINE_STATE_DESC wavesRenderPSO = transparentPsoDesc;
//	wavesRenderPSO.VS =
//	{
//		reinterpret_cast<BYTE*>(mShaders["wavesVS"]->GetBufferPointer()),
//		mShaders["wavesVS"]->GetBufferSize()
//	};
//	ThrowIfFailed(md3dDevice->CreateGraphicsPipelineState(&wavesRenderPSO, IID_PPV_ARGS(&mPSOs["wavesRender"])));
//
//	//
//	// PSO for disturbing waves
//	//
//	D3D12_COMPUTE_PIPELINE_STATE_DESC wavesDisturbPSO = {};
//	wavesDisturbPSO.pRootSignature = mWavesRootSignature.Get();
//	wavesDisturbPSO.CS =
//	{
//		reinterpret_cast<BYTE*>(mShaders["wavesDisturbCS"]->GetBufferPointer()),
//		mShaders["wavesDisturbCS"]->GetBufferSize()
//	};
//	wavesDisturbPSO.Flags = D3D12_PIPELINE_STATE_FLAG_NONE;
//	ThrowIfFailed(md3dDevice->CreateComputePipelineState(&wavesDisturbPSO, IID_PPV_ARGS(&mPSOs["wavesDisturb"])));
//
//	//
//	// PSO for updating waves
//	//
//	D3D12_COMPUTE_PIPELINE_STATE_DESC wavesUpdatePSO = {};
//	wavesUpdatePSO.pRootSignature = mWavesRootSignature.Get();
//	wavesUpdatePSO.CS =
//	{
//		reinterpret_cast<BYTE*>(mShaders["wavesUpdateCS"]->GetBufferPointer()),
//		mShaders["wavesUpdateCS"]->GetBufferSize()
//	};
//	wavesUpdatePSO.Flags = D3D12_PIPELINE_STATE_FLAG_NONE;
//	ThrowIfFailed(md3dDevice->CreateComputePipelineState(&wavesUpdatePSO, IID_PPV_ARGS(&mPSOs["wavesUpdate"])));
//}
//
//void WavesCSApp::BuildFrameResources()
//{
//    for(int i = 0; i < gNumFrameResources; ++i)
//    {
//        mFrameResources.push_back(std::make_unique<WavesCSFrameResource>(md3dDevice.Get(),
//            1, (UINT)mAllRitems.size(), (UINT)mMaterials.size()));
//    }
//}
//
//void WavesCSApp::BuildMaterials()
//{
//	auto grass = std::make_unique<Material>();
//	grass->Name = "grass";
//	grass->MatCBIndex = 0;
//	grass->DiffuseSrvHeapIndex = 0;
//	grass->DiffuseAlbedo = XMFLOAT4(1.0f, 1.0f, 1.0f, 1.0f);
//	grass->FresnelR0 = XMFLOAT3(0.01f, 0.01f, 0.01f);
//	grass->Roughness = 0.125f;
//
//	// This is not a good water material definition, but we do not have all the rendering
//	// tools we need (transparency, environment reflection), so we fake it for now.
//	auto water = std::make_unique<Material>();
//	water->Name = "water";
//	water->MatCBIndex = 1;
//	water->DiffuseSrvHeapIndex = 1;
//	water->DiffuseAlbedo = XMFLOAT4(1.0f, 1.0f, 1.0f, 0.5f);
//	water->FresnelR0 = XMFLOAT3(0.1f, 0.1f, 0.1f);
//	water->Roughness = 0.0f;
//
//	auto wirefence = std::make_unique<Material>();
//	wirefence->Name = "wirefence";
//	wirefence->MatCBIndex = 2;
//	wirefence->DiffuseSrvHeapIndex = 2;
//	wirefence->DiffuseAlbedo = XMFLOAT4(1.0f, 1.0f, 1.0f, 1.0f);
//	wirefence->FresnelR0 = XMFLOAT3(0.02f, 0.02f, 0.02f);
//	wirefence->Roughness = 0.25f;
//
//	mMaterials["grass"] = std::move(grass);
//	mMaterials["water"] = std::move(water);
//	mMaterials["wirefence"] = std::move(wirefence);
//}
//
//void WavesCSApp::BuildRenderItems()
//{
//    auto wavesRitem = std::make_unique<RenderItem>();
//    wavesRitem->World = MathHelper::Identity4x4();
//	XMStoreFloat4x4(&wavesRitem->TexTransform, XMMatrixScaling(5.0f, 5.0f, 1.0f));
//	wavesRitem->DisplacementMapTexelSize.x = 1.0f / mWaves->ColumnCount();
//	wavesRitem->DisplacementMapTexelSize.y = 1.0f / mWaves->RowCount();
//	wavesRitem->GridSpatialStep = mWaves->SpatialStep();
//	wavesRitem->ObjCBIndex = 0;
//	wavesRitem->Mat = mMaterials["water"].get();
//	wavesRitem->Geo = mGeometries["waterGeo"].get();
//	wavesRitem->PrimitiveType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
//	wavesRitem->IndexCount = wavesRitem->Geo->DrawArgs["grid"].IndexCount;
//	wavesRitem->StartIndexLocation = wavesRitem->Geo->DrawArgs["grid"].StartIndexLocation;
//	wavesRitem->BaseVertexLocation = wavesRitem->Geo->DrawArgs["grid"].BaseVertexLocation;
//
//	mRitemLayer[(int)RenderLayer::GpuWavesCS].push_back(wavesRitem.get());
//
//    auto gridRitem = std::make_unique<RenderItem>();
//    gridRitem->World = MathHelper::Identity4x4();
//	XMStoreFloat4x4(&gridRitem->TexTransform, XMMatrixScaling(5.0f, 5.0f, 1.0f));
//	gridRitem->ObjCBIndex = 1;
//	gridRitem->Mat = mMaterials["grass"].get();
//	gridRitem->Geo = mGeometries["landGeo"].get();
//	gridRitem->PrimitiveType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
//    gridRitem->IndexCount = gridRitem->Geo->DrawArgs["grid"].IndexCount;
//    gridRitem->StartIndexLocation = gridRitem->Geo->DrawArgs["grid"].StartIndexLocation;
//    gridRitem->BaseVertexLocation = gridRitem->Geo->DrawArgs["grid"].BaseVertexLocation;
//
//	mRitemLayer[(int)RenderLayer::Opaque].push_back(gridRitem.get());
//
//	auto boxRitem = std::make_unique<RenderItem>();
//	XMStoreFloat4x4(&boxRitem->World, XMMatrixTranslation(3.0f, 2.0f, -9.0f));
//	boxRitem->ObjCBIndex = 2;
//	boxRitem->Mat = mMaterials["wirefence"].get();
//	boxRitem->Geo = mGeometries["boxGeo"].get();
//	boxRitem->PrimitiveType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
//	boxRitem->IndexCount = boxRitem->Geo->DrawArgs["box"].IndexCount;
//	boxRitem->StartIndexLocation = boxRitem->Geo->DrawArgs["box"].StartIndexLocation;
//	boxRitem->BaseVertexLocation = boxRitem->Geo->DrawArgs["box"].BaseVertexLocation;
//
//	mRitemLayer[(int)RenderLayer::AlphaTested].push_back(boxRitem.get());
//
//    mAllRitems.push_back(std::move(wavesRitem));
//    mAllRitems.push_back(std::move(gridRitem));
//	mAllRitems.push_back(std::move(boxRitem));
//}
//
//void WavesCSApp::DrawRenderItems(ID3D12GraphicsCommandList* cmdList, const std::vector<RenderItem*>& ritems)
//{
//    UINT objCBByteSize = d3dUtil::CalcConstantBufferByteSize(sizeof(ObjectConstants));
//    UINT matCBByteSize = d3dUtil::CalcConstantBufferByteSize(sizeof(MaterialConstants));
//
//	auto objectCB = mCurrFrameResource->ObjectCB->Resource();
//	auto matCB = mCurrFrameResource->MaterialCB->Resource();
//
//    // For each render item...
//    for(size_t i = 0; i < ritems.size(); ++i)
//    {
//        auto ri = ritems[i];
//
//        cmdList->IASetVertexBuffers(0, 1, &ri->Geo->VertexBufferView());
//        cmdList->IASetIndexBuffer(&ri->Geo->IndexBufferView());
//        cmdList->IASetPrimitiveTopology(ri->PrimitiveType);
//
//		CD3DX12_GPU_DESCRIPTOR_HANDLE tex(mSrvDescriptorHeap->GetGPUDescriptorHandleForHeapStart());
//		tex.Offset(ri->Mat->DiffuseSrvHeapIndex, mCbvSrvDescriptorSize);
//
//        D3D12_GPU_VIRTUAL_ADDRESS objCBAddress = objectCB->GetGPUVirtualAddress() + ri->ObjCBIndex*objCBByteSize;
//		D3D12_GPU_VIRTUAL_ADDRESS matCBAddress = matCB->GetGPUVirtualAddress() + ri->Mat->MatCBIndex*matCBByteSize;
//
//		cmdList->SetGraphicsRootDescriptorTable(0, tex);
//        cmdList->SetGraphicsRootConstantBufferView(1, objCBAddress);
//        cmdList->SetGraphicsRootConstantBufferView(3, matCBAddress);
//
//        cmdList->DrawIndexedInstanced(ri->IndexCount, 1, ri->StartIndexLocation, ri->BaseVertexLocation, 0);
//    }
//}
//
//std::array<const CD3DX12_STATIC_SAMPLER_DESC, 6> WavesCSApp::GetStaticSamplers()
//{
//	// Applications usually only need a handful of samplers.  So just define them all up front
//	// and keep them available as part of the root signature.  
//
//	const CD3DX12_STATIC_SAMPLER_DESC pointWrap(
//		0, // shaderRegister
//		D3D12_FILTER_MIN_MAG_MIP_POINT, // filter
//		D3D12_TEXTURE_ADDRESS_MODE_WRAP,  // addressU
//		D3D12_TEXTURE_ADDRESS_MODE_WRAP,  // addressV
//		D3D12_TEXTURE_ADDRESS_MODE_WRAP); // addressW
//
//	const CD3DX12_STATIC_SAMPLER_DESC pointClamp(
//		1, // shaderRegister
//		D3D12_FILTER_MIN_MAG_MIP_POINT, // filter
//		D3D12_TEXTURE_ADDRESS_MODE_CLAMP,  // addressU
//		D3D12_TEXTURE_ADDRESS_MODE_CLAMP,  // addressV
//		D3D12_TEXTURE_ADDRESS_MODE_CLAMP); // addressW
//
//	const CD3DX12_STATIC_SAMPLER_DESC linearWrap(
//		2, // shaderRegister
//		D3D12_FILTER_MIN_MAG_MIP_LINEAR, // filter
//		D3D12_TEXTURE_ADDRESS_MODE_WRAP,  // addressU
//		D3D12_TEXTURE_ADDRESS_MODE_WRAP,  // addressV
//		D3D12_TEXTURE_ADDRESS_MODE_WRAP); // addressW
//
//	const CD3DX12_STATIC_SAMPLER_DESC linearClamp(
//		3, // shaderRegister
//		D3D12_FILTER_MIN_MAG_MIP_LINEAR, // filter
//		D3D12_TEXTURE_ADDRESS_MODE_CLAMP,  // addressU
//		D3D12_TEXTURE_ADDRESS_MODE_CLAMP,  // addressV
//		D3D12_TEXTURE_ADDRESS_MODE_CLAMP); // addressW
//
//	const CD3DX12_STATIC_SAMPLER_DESC anisotropicWrap(
//		4, // shaderRegister
//		D3D12_FILTER_ANISOTROPIC, // filter
//		D3D12_TEXTURE_ADDRESS_MODE_WRAP,  // addressU
//		D3D12_TEXTURE_ADDRESS_MODE_WRAP,  // addressV
//		D3D12_TEXTURE_ADDRESS_MODE_WRAP,  // addressW
//		0.0f,                             // mipLODBias
//		8);                               // maxAnisotropy
//
//	const CD3DX12_STATIC_SAMPLER_DESC anisotropicClamp(
//		5, // shaderRegister
//		D3D12_FILTER_ANISOTROPIC, // filter
//		D3D12_TEXTURE_ADDRESS_MODE_CLAMP,  // addressU
//		D3D12_TEXTURE_ADDRESS_MODE_CLAMP,  // addressV
//		D3D12_TEXTURE_ADDRESS_MODE_CLAMP,  // addressW
//		0.0f,                              // mipLODBias
//		8);                                // maxAnisotropy
//
//	return { 
//		pointWrap, pointClamp,
//		linearWrap, linearClamp, 
//		anisotropicWrap, anisotropicClamp };
//}
//
//float WavesCSApp::GetHillsHeight(float x, float z)const
//{
//    return 0.3f*(z*sinf(0.1f*x) + x*cosf(0.1f*z));
//}
//
//XMFLOAT3 WavesCSApp::GetHillsNormal(float x, float z)const
//{
//    // n = (-df/dx, 1, -df/dz)
//    XMFLOAT3 n(
//        -0.03f*z*cosf(0.1f*x) - 0.3f*cosf(0.1f*z),
//        1.0f,
//        -0.3f*sinf(0.1f*x) + 0.03f*x*sinf(0.1f*z));
//
//    XMVECTOR unitNormal = XMVector3Normalize(XMLoadFloat3(&n));
//    XMStoreFloat3(&n, unitNormal);
//
//    return n;
//}
